package com.hjx.leetcode;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.LockSupport;

/**
 * 控制线程的执行顺序
 * 解法3、LockSupport.park unpark， 此种方案会失败，导致的结果有以下几个
 * 1、程序被挂起，原因在于不能保证first中的unpark调用一定在 执行second的线程park之后，导致了执行second和third 的两个（可能）线程被挂起，一直无法恢复
 * 2、线程还未执行完成就退出，只输出了first
 */
class LeetCode_1114_solution3 {

    public ConcurrentHashMap</*methodname*/String, Thread> concurrentHashMap = new ConcurrentHashMap</*methodname*/String, Thread>();

    private static String getExecutingMethodName() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        StackTraceElement e = stackTrace[2];
        return e.getMethodName();
    }

    public void first(Runnable printFirst) throws InterruptedException {

//        concurrentHashMap.put(getExecutingMethodName(), Thread.currentThread());
//        LockSupport.park();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        LockSupport.parkUntil(System.currentTimeMillis() + 300);
        //开启second
        LockSupport.unpark(concurrentHashMap.get("second"));
    }

    public void second(Runnable printSecond) throws InterruptedException {

        concurrentHashMap.put(getExecutingMethodName(), Thread.currentThread());
        System.out.println(Thread.currentThread() + " 即将挂起");
        LockSupport.park();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        //开启third
        LockSupport.unpark(concurrentHashMap.get("third"));
    }

    public void third(Runnable printThird) throws InterruptedException {

        concurrentHashMap.put(getExecutingMethodName(), Thread.currentThread());
        System.out.println(Thread.currentThread() + " 即将挂起");
        LockSupport.park();
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }

}
